#ifndef __INSTANCE_MANAGER_H__
  #define __INSTANCE_MANAGER_H__

#include "list.h"

namespace memory_management {

//! Instance manager for objects

/*!
Allocating too many small objects can cause performance problems. That is why this class can
help to reduce the overhead of object creation by allocating arrays of objects.
This means, that we do fewer allocation operations, but each time we allocate enough memory for
many instances.

All allocated instances will be freed when destructing this class.
The destructor is not defined virtual because of efficiency reasons, please do not inherit from
this class.

Implementation date: 2008

Usage:

\code
memory_management::instance_manager<int> im;

for (int i = 0; i < 100; ++i) {
  int *var = im.get_new_instance();
  *var = i;
  cout << *var <<endl;
}
\endcode
*/

  template <class T, unsigned short CAPACITY = 256>
  class instance_manager {
  private:
    list<T*> arrays; // list of allocated arrays
    T *buffer;
    unsigned short counter;

    //! assignment operator: not allowed
    instance_manager &operator=(const instance_manager &im);

    //! copy constructor: not allowed
    instance_manager(const instance_manager &im);

    void allocate() {
      buffer = new T[CAPACITY];
      counter = 0;
      arrays.prepend(new node<T*>(buffer));
    } // allocate

  public:
    //! releases all nodes and frees the allocated memory
    void release() {
      node<T*> *tmp = arrays.get_head();
      while (tmp != 0) {
        delete[] tmp->get_value();
        tmp = tmp->get_next();
      } // while

      arrays.release();
      counter = 0;
      buffer = 0;
    } // release

    //! returns a new instance. may cause new memory allocations
    T *get_new_instance() {
      if (counter == CAPACITY || buffer == 0)
        allocate();

      return &buffer[counter++];
    } // get_new_instance

    //! default constructor
    instance_manager() : buffer(0), counter(0) {
      // nothing to do
    } // instance_manager

    //! destructor (non-virtual: please do not inherit from this class)
    ~instance_manager() {
      release();
    } // ~instance_manager
  }; // class instance_manager

} // namespace memory_management

#endif
